package main

import (
	"fmt"
	_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/os/gcron"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/gogf/gf/v2/text/gstr"
	"io"
	"strings"
	"time"
)

var s *ghttp.Server
var email = ""
var domain = ""
var isSSlAuto = false
var aliDnsKey = ""
var aliDnsSec = ""
var ssl_cron = ""
var ctx = gctx.New()

type ProxyInfo struct {
	Address string
	Host    bool
}

var proxyStr = map[string]ProxyInfo{}

func main() {
	email = g.Cfg().MustGet(ctx, "app.ssl_email", "").String()
	domain = g.Cfg().MustGet(ctx, "app.ssl_domain", "").String()
	isSSlAuto = g.Cfg().MustGet(ctx, "app.ssl_enable", false).Bool()
	aliDnsKey = g.Cfg().MustGet(ctx, "app.ssl_aliKey", "").String()
	aliDnsSec = g.Cfg().MustGet(ctx, "app.ssl_aliSec", "").String()
	ssl_cron = g.Cfg().MustGet(ctx, "app.ssl_cron", "0 0 23 1 2/2 ?").String()

	err := g.Cfg().MustGet(ctx, "app.proxy").Scan(&proxyStr)
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}
	StartProxyServer()
	gcron.Start()
	//关联服务
	startServerManager()
}

func StartProxyServer() {
	if s != nil {
		err := s.Shutdown()
		if err != nil {
			g.Log().Error(ctx, err)
		}
		//s.SetTLSConfig()
	}
	s = g.Server("proxy")
	initSslAuto()
	initOrm()
	initProxyStr()

	s.BindHandler("/*", ProxySsl())
	if isSSlAuto {
		//s.EnableHTTPS(myLego.CertPath, myLego.KeyPath, &tls.Config{
		//	MinVersion: tls.VersionTLS12,
		//	MaxVersion: tls.VersionTLS13,
		//})
		g.Log().Print(ctx, "代理服务 加载ssl", myLego.CertPath, myLego.KeyPath)
		err := UpdateSsl(myLego.CertPath, myLego.KeyPath, s)
		if err != nil {
			g.Log().Error(ctx, "代理服务 加载ssl", err)
			return
		}
		g.Log().Print(ctx, "代理服务 加载ssl 成功")
	}
	s.SetFileServerEnabled(false)
	err := s.Start()
	if err != nil {
		g.Log().Print(ctx, "代理服务 启动失败")
		g.Log().Fatal(ctx, err)
	}
	g.Log().Print(ctx, "代理服务 启动成功")
}

func ProxySsl() interface{} {
	var doMain = gstr.TrimLeft(domain, "*")
	return func(r *ghttp.Request) {
		if !gstr.IsSubDomain(r.Host, domain) {
			r.Response.Writeln("不支持域名 【" + r.Host + "】 的代理 ,域名 ")
			return
		}
		prevIndex := strings.Index(r.Host, doMain)
		prev := gstr.Trim(r.Host[:prevIndex], ".")
		p, ok := proxyStr[prev]
		if !ok {
			r.Response.Writeln("未配置域名前缀 【" + prev + "】 的代理.")
			return
		}

		reqBodyBytes, _ := io.ReadAll(r.Request.Body)
		startTime := time.Now()

		defer func() {
			g.Log().Info(ctx, p.Address+r.URL.String(), r.Method, time.Since(startTime))
		}()
		var httpClient = g.Client()
		for s2, strings2 := range r.Header {
			for _, s3 := range strings2 {
				httpClient.SetHeader(s2, s3)
			}
		}
		if p.Host {
			httpClient = httpClient.
				SetHeader("X-Real-IP", r.GetClientIp()).
				SetHeader("Host", r.Host).
				SetHeader("X-Forwarded-For", r.GetClientIp())
		}
		bs, err := httpClient.
			DoRequest(ctx, r.Method, p.Address+r.URL.String(), reqBodyBytes)
		if err != nil {
			g.Log().Error(ctx, err)
			return
		}
		r.Response.Status = bs.StatusCode
		for s2, strings := range bs.Header {
			for _, s3 := range strings {
				r.Response.Header().Add(s2, s3)
			}
		}
		bodyBytes, err := io.ReadAll(bs.Response.Body)
		if err != nil {
			g.Log().Error(ctx, err)
			return
		}
		r.Response.Write(bodyBytes)
		return
	}
}

func initProxyStr() {
	all, err := g.Model("t_address").Where("enable = ?", "Y").All()
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}
	for _, record := range all {
		m := record.Map()
		var name = fmt.Sprintf("%v", m["name"])
		var address = fmt.Sprintf("%v", m["address"])

		g.Log().Print(ctx, name, address)
		proxyStr[name] = ProxyInfo{
			Address: address,
			Host:    m["host"] == 1,
		}
	}
	g.Log().Print(ctx, proxyStr)
}

//func RestartWebServer() error {
//	//StartProxyServer()
//	//return nil
//	/*if err := s.Shutdown(); err != nil {
//		g.Log().Error(ctx, "shutdown 重启服务器失败", err)
//		return err
//	}
//	if err := s.Start(); err != nil {
//		g.Log().Error(ctx, "start 重启服务器失败", err)
//		return err
//	}
//	return nil*/
//}
